﻿
#include "AbilitySystem/AuraAbilityTypes.h"

bool FAuraGameplayEffectContext::NetSerialize(FArchive& Ar, UPackageMap* Map, bool& bOutSuccess)
{
	uint32 RepBits = 0;
	if (Ar.IsSaving())
	{
		//保存数据时，如果有对应的配置项数据，那么将对应位的值设置为1
		if (bReplicateInstigator && Instigator.IsValid())
		{
			RepBits |= 1 << 0;
		}

		if (bReplicateEffectCauser && EffectCauser.IsValid())
		{
			RepBits |= 1 << 1;
		}

		if (AbilityCDO.IsValid())
		{
			RepBits |= 1 << 2;
		}

		if (bReplicateSourceObject && SourceObject.IsValid())
		{
			RepBits |= 1 << 3;
		}

		if (Actors.Num() > 0)
		{
			RepBits |= 1 << 4;
		}

		if (HitResult.IsValid())
		{
			RepBits |= 1 << 5;
		}

		if (bHasWorldOrigin)
		{
			RepBits |= 1 << 6;
		}

		if (bIsBlockedHit)
		{
			RepBits |= 1 << 7;
		}

		if (bIsCriticalHit)
		{
			RepBits |= 1 << 8;
		}
	}

	// 序列化BepBits
	Ar.SerializeBits(&RepBits, 9);

	// 根据标志位序列化对应数据
	//如果对应位的值为1，那么将数据存入Ar
	if (RepBits & (1 << 0))
	{
		Ar << Instigator;
	}

	if (RepBits & (1 << 1))
	{
		Ar << EffectCauser;
	}

	if (RepBits & (1 << 2))
	{
		Ar << AbilityCDO;
	}

	if (RepBits & (1 << 3))
	{
		Ar << SourceObject;
	}

	if (RepBits & (1 << 4))
	{
		SafeNetSerializeTArray_Default<31>(Ar, Actors);
	}

	if (RepBits & (1 << 5))
	{
		if (Ar.IsLoading())
		{
			// 确保HitResult有效
			if (!HitResult.IsValid())
			{
				HitResult = MakeShared<FHitResult>();
			}
		}
		HitResult->NetSerialize(Ar, Map, bOutSuccess);
	}

	if (RepBits & (1 << 6))
	{
		Ar << WorldOrigin;
		bHasWorldOrigin = true;
	}
	else
	{
		bHasWorldOrigin = false;
	}

	//如果是加载数据（即反序列化）时，需要调用对ASC进行初始化
	if (Ar.IsLoading())
	{
		AddInstigator(Instigator.Get(), EffectCauser.Get());
	}

	if (RepBits & (1<< 7))
	{
		Ar << bIsBlockedHit;
	}

	if (RepBits & (1 << 8))
	{
		Ar << bIsCriticalHit;
	}

	bOutSuccess = true;
	return true;
}
// AActor* Instigator;
// AActor* EffectCauser;
// UObject* SourceObject;
// 这些是UE中的对象(UObject)指针
// - 它们指向的对象由UE引擎管理
// - 不需要也不应该深拷贝这些对象
// - 复制指针引用就足够了
// 需要深拷贝因为：
// - HitResult包含详细的碰撞信息
// - 可能会被后续代码修改
// - 需要独立的副本以避免共享状态

// 创建一个副本，用于后续网络复制或者后续修改
FAuraGameplayEffectContext* FAuraGameplayEffectContext::Duplicate() const
{
	// 创建新上下文
	FAuraGameplayEffectContext* NewContext = new FAuraGameplayEffectContext();
	// 浅拷贝所有成员
	*NewContext = *this;
	if (GetHitResult())
	{
		// AddHitResult实现里会深拷贝 hit result
		NewContext->AddHitResult(*GetHitResult(), true);
	}
	return NewContext;
}
